package org.example.ims.Service.WarehouseProduct.Impl;


import org.example.ims.DTO.InventoryItemDTO;
import org.example.ims.DTO.ProductWithInventoryDTO;
import org.example.ims.DTO.StockInOutDTO;
import org.example.ims.Entity.Base.Product;
import org.example.ims.Entity.Base.Warehouse;
import org.example.ims.Entity.WareHouseProduct.WarehouseProduct;
import org.example.ims.Entity.WareHouseProduct.WarehouseProductId;
import org.example.ims.Repository.Base.WarehouseRepository;
import org.example.ims.Repository.WarehouseProduct.WarehouseProductRepository;
import org.example.ims.Service.Base.ProductService;
import org.example.ims.Service.Base.WarehouseService;
import org.example.ims.Service.WarehouseProduct.WarehouseProductService;
import org.example.ims.Utils.Detail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

import static org.example.ims.Utils.WarehouseProductSpecifications.buildSpecification;

@Service("warehouseProductService")
public class WarehouseProductServiceImpl implements WarehouseProductService {

    @Autowired
    private  WarehouseProductRepository warehouseProductRepository;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private ProductService productService;
    @Autowired
    private WarehouseRepository warehouseRepository;

    @Override
    public WarehouseProduct createWarehouseProduct(WarehouseProduct warehouseProduct) {
        return warehouseProductRepository.save(warehouseProduct);
    }

    @Override
    public Optional<WarehouseProduct> findById(WarehouseProductId id) {
        return warehouseProductRepository.findById(id);
    }

    @Override
    public WarehouseProduct updateWarehouseProduct(WarehouseProduct warehouseProduct) {
        return warehouseProductRepository.save(warehouseProduct);
    }

    @Override
    public void deleteWarehouseProduct(WarehouseProductId id) {
        warehouseProductRepository.deleteById(id);
    }

    @Override
    public Page<WarehouseProduct> searchWarehouseProducts(Integer warehouseId, Integer productId,
                                                           Integer minStock, Integer maxStock,
                                                           Integer page, Integer size){
        Specification<WarehouseProduct> specification=  buildSpecification(warehouseId,productId,minStock,maxStock);
        return warehouseProductRepository.findAll(specification, PageRequest.of(page, size));

    }

    @Transactional
    @Override
    public void stockIn(Warehouse warehouse, StockInOutDTO<Product> inStockDTO) {
        List<Detail<Product>>details = inStockDTO.getDetails();
        Integer allNeed= inStockDTO.getAllNeed();
        //遍历所有details进行处理
        for(Detail<Product> detail:details){
            Product product =detail.getItem();
            Integer quantity =detail.getQuantity();
            Optional<WarehouseProduct> warehouseProduct = warehouseProductRepository.
                    findByWarehouseAndProduct(warehouse,product);

            WarehouseProduct wp ;
            //根据是否已经有WP记录进行入库
            if (warehouseProduct.isPresent()) {
                wp = warehouseProduct.get();
                wp.setQuantity(wp.getQuantity() + quantity);
            } else {//创建一个WP
                wp  = new WarehouseProduct();
                WarehouseProductId warehouseProductId = new WarehouseProductId(
                        warehouse.getWarehouseId(), product.getProductId());
                wp.setId(warehouseProductId);
                wp.setQuantity(quantity);
            }
            //对于对应的product的stock进行改变
            Integer oldStock=product.getProductStock();
            product.setProductStock(oldStock + quantity);
            wp.setProduct(product);
            wp.setWarehouse(warehouse);
            //通过外键关联实体，save对于关联的Product也会改变
            warehouseProductRepository.save(wp);
        }
        //最后对于仓库容量的更改
        warehouse.setUsedCapacity(warehouse.getUsedCapacity()+allNeed);
        warehouseRepository.save(warehouse);
    }

    @Transactional
    @Override
    public void stockOut(Warehouse warehouse, StockInOutDTO<WarehouseProduct> outStockDTO) {
        List<Detail<WarehouseProduct>> details = outStockDTO.getDetails();
        Integer allNeed = outStockDTO.getAllNeed();

        // 遍历所有 details 进行处理
        for (Detail<WarehouseProduct> detail : details) {
            WarehouseProduct warehouseProduct =detail.getItem();
            Integer quantity = detail.getQuantity();

            Product product = warehouseProduct.getProduct();
            Integer currentStock = warehouseProduct.getQuantity();

            // 减少库存数量
            warehouseProduct.setQuantity(currentStock - quantity);

            // 更新产品的总库存
            Integer oldStock = product.getProductStock();
            product.setProductStock(oldStock - quantity);

            // 保存更新后的 WarehouseProduct 和 Product
            warehouseProductRepository.save(warehouseProduct);
        }

        // 更新仓库容量
        warehouse.setUsedCapacity(warehouse.getUsedCapacity() - allNeed);
        warehouseRepository.save(warehouse);
    }


    @Transactional
    @Override
    public void transferStock(Warehouse sourceWarehouse, Warehouse targetWarehouse,
                              StockInOutDTO<Product> inStockDTO, StockInOutDTO<WarehouseProduct> outStockDTO) {
        // Deduct from source warehouse
        stockOut(sourceWarehouse,outStockDTO);

        // Add to target warehouse
        stockIn(targetWarehouse,inStockDTO );
    }

    @Override
    public Page<ProductWithInventoryDTO> searchProducts(Integer warehouseId, String status, Integer page, Integer size) {
        return warehouseProductRepository.findProductsWithInventoryByConditions(warehouseId,status,PageRequest.of(page,size));

    }

    @Override
    public Page<InventoryItemDTO> queryInventory(Integer warehouseId, Integer categoryId, String productStatus, String productName, Integer minStock, Integer maxStock, Integer page, Integer size) {
        return warehouseProductRepository.findProductsWithInventoryByConditions(warehouseId,categoryId,productStatus,productName,minStock,maxStock,PageRequest.of(page,size));
    }
}